//@author A0105543N
#include "Trash.h"

void Trash::add_Expense( XpensItem origin, XpensItem current)
{
	UndoExpense.push_back ( pair< XpensItem, XpensItem >( origin, current ) );
	checkUndo();
}

void Trash::add_Payment(PaymentItem origin, PaymentItem current){
	UndoPayment.push_back ( pair< PaymentItem, PaymentItem >( origin, current ) );
	checkUndo();
}

void Trash::addOperation( int operation)
{
	Operation.push_back(operation);
}


XpensItem Trash::getNewExpense()
{
	return (UndoExpense.end() - 1) -> second;
}

XpensItem Trash::getOriginExpense()//this indicates that undo has been called, so this operation should be pushed into redo vector
{
	XpensItem target = (UndoExpense.end() - 1) -> first;
	RedoExpense.push_back(*(UndoExpense.end() - 1));
	UndoExpense.pop_back();
	checkRedo();
	return target;
}

int Trash::getOperation()
{
	if (Operation.empty()) return 0;
	int target = *(Operation.end() - 1);
	RedoOperation.push_back(target);
	Operation.pop_back();
	return target;
}

int Trash::getRedoOperation()
{
	if (RedoOperation.empty()) return 0;
	int target = *(RedoOperation.end() - 1);
	RedoOperation.pop_back();
	Operation.push_back(target);
	return target;
}

XpensItem Trash::getRedoNewExpense()
{
	XpensItem target = (RedoExpense.end() - 1) -> second;
	add_Expense((RedoExpense.end() - 1) -> first,(RedoExpense.end() - 1) -> second);
	RedoExpense.pop_back();
	return target;
}

XpensItem Trash::getRedoOriginExpense()
{
	return (RedoExpense.end() - 1) -> first;
}

void Trash::checkUndo()
{
	if (Operation.size() > maxnoperation) {
	switch (Operation[0]){
	case 1: UndoPayment.erase(UndoPayment.begin());
		break;
	case -1:UndoExpense.erase(UndoExpense.begin());
		break;
	case 2:UndoPayCategory.erase(UndoPayCategory.begin());
		break;
	case -2:UndoExpCategory.erase(UndoExpCategory.begin());
		break;
	}
	Operation.erase(Operation.begin());
	}

}

void Trash::checkRedo()
{
	if (RedoOperation.size() > maxnoperation) {
	switch (RedoOperation[0]){
	case 1: RedoPayment.erase(RedoPayment.begin());
		break;
	case -1:RedoExpense.erase(RedoExpense.begin());
		break;
	case 2:RedoPayCategory.erase(RedoPayCategory.begin());
		break;
	case -2:RedoExpCategory.erase(RedoExpCategory.begin());
		break;
	}
	RedoOperation.erase(RedoOperation.begin());
	}
}

PaymentItem Trash::getOriginPayment()
{
	PaymentItem target = (UndoPayment.end() -1) -> first;
	RedoPayment.push_back(*(UndoPayment.end() - 1));
	UndoPayment.pop_back();
	checkRedo();
	return target;
}

PaymentItem Trash::getNewPayment()
{
	return (UndoPayment.end() - 1) -> second;
}

PaymentItem Trash::getRedoNewPayment()
{
	PaymentItem target = (RedoPayment.end() - 1) -> second;
	add_Payment((RedoPayment.end() -1) -> first, (RedoPayment.end() - 1) -> second);
	RedoPayment.pop_back();
	return target;
}

PaymentItem Trash::getRedoOriginPayment()
{
	return (RedoPayment.end() - 1) -> first;
}

void Trash::add_ExpCategory(int ID, string category)
{
	Operation.push_back(-2);
	UndoExpCategory.push_back( pair<int,string> (ID,category));
	checkUndo();
}

void Trash::add_PayCategory(int ID, string category)
{
	Operation.push_back(2);
	UndoPayCategory.push_back( pair<int, string> (ID, category));
	checkUndo();
}

void Trash::getUndoExpCategory(int& ID, string& category)//this indicate Redo has been called, so it should be pushed into undo vector
{
	ID = (UndoExpCategory.end() - 1) -> first;
	category = (UndoExpCategory.end() - 1) -> second;
	UndoExpCategory.pop_back();
	RedoExpCategory.push_back(pair<int,string>(ID,category));
	checkRedo();
}
void Trash::getUndoPayCategory(int& ID, string& category)
{
	ID = (UndoPayCategory.end() - 1) -> first;
	category = (UndoPayCategory.end() - 1) -> second;
	UndoPayCategory.pop_back();
	RedoPayCategory.push_back(pair<int,string>(ID,category));
	checkRedo();
}

void Trash::getRedoExpCategory(int& ID,string& category)
{
	ID = (RedoExpCategory.end() - 1) -> first;
	category = (RedoExpCategory.end() - 1) -> second;
	RedoExpCategory.pop_back();
	UndoExpCategory.push_back(pair<int,string>(ID,category));
	checkUndo();
}

void Trash::getRedoPayCategory(int& ID, string& category)
{
	ID = (RedoPayCategory.end() - 1) -> first;
	category = (RedoPayCategory.end() - 1) -> second;
	RedoPayCategory.pop_back();
	UndoPayCategory.push_back(pair<int,string>(ID,category));
	checkUndo();
}